package cn.initcap.designpattern.pattern.creational.singleton;

import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.RandomUtils;

/**
 * @author initcap
 * @date 2018/8/28 AM9:09
 */
public class LazyDoubleCheckSingleton {

    /**
     * volatile修饰的变量会让所有线程看到最新的共享内存的状态，保证了内存的可见性；
     * 使用的是缓存一致性协议；
     */
    private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;
    private volatile static Map<String, Integer> map = new HashMap<>();

    private LazyDoubleCheckSingleton() {

    }

    /**
     * 比较LazySingleton兼顾了性能和安全问题！
     *
     * @return
     */
    public static LazyDoubleCheckSingleton getInstance() {
        if (lazyDoubleCheckSingleton == null) {
            synchronized (LazyDoubleCheckSingleton.class) {
                if (lazyDoubleCheckSingleton == null) {
                    /*
                    Java初始化对象步骤（下面2、3步骤可能会被指令重排序）：
                    1.分配内存给这个对象
                    2.初始化对象
                    3.设置lazyDoubleCheckSingleton 指向刚分配的内存地址
                     */
                    lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
                }
            }
        }
        return lazyDoubleCheckSingleton;
    }

    /**
     * 单例模式的属性也存在线程安全问题，需要加锁！
     * @param key
     * @return
     * @throws InterruptedException
     */
    public Integer getValue(String key) throws InterruptedException {
        Integer val = map.get(key);
        if (val == null) {
            synchronized (this) {
                val = map.get(key);
                if (val == null) {
                    Thread.sleep(1000);
                    int i = RandomUtils.nextInt();
                    map.put(key, i);
                    return i;
                }
            }
        }
        return val;
    }
}
